// （1）理解CowString关于引用计数的设计思路，复现课上初步实现的代码，尝试进一步实现赋值运算符函数；

// （2）对CowString进行下标运算符重载，参考讲义解决区分取下标后读写的问题（较难）；

// （3）了解SSO设计思想；

// （4）预习set、map的基本使用（在继承之前讲这一章）

// 酌情安排自己的复习、预习

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <cstring>

using std::cout;
using std::endl;
using std::cin;
using std::istream;
using std::ostream;
using std::vector;
using std::string;

class String
{
    class CharProxy
    {
    public:
        CharProxy(String& self, int index);
        void operator=(const char& ch);
        operator char();
    private:
        String& _self;
        int _index;
    };
public:
    String();
    String(const char* pstr);
    String(const String& rhs);
    ~String();
    String& operator=(const String& rhs);
    CharProxy operator[](int index);
    const char& operator[](int index) const;
    void print(void) const;
    size_t size() const;
private:
    void init_count(void);
    void insert_count(void);
    void minus_count(void);
    bool is_zero_count(void) const;
    const int& get_count(void) const;
private:
    char* _pstr;
    static int _int_lenth;
};
int String::_int_lenth = 4;

String::String()
    : _pstr(new char[_int_lenth + 1] + _int_lenth){
    init_count();
    cout << "String()" << endl;
}
String::String(const char* pstr)
    : _pstr(new char[_int_lenth + strlen(pstr) + 1] + _int_lenth){
    cout << "String(const char* pstr)" << endl;
    init_count();
    strcpy(_pstr, pstr);
}
String::String(const String& rhs)
    : _pstr(rhs._pstr){
    cout << "String(const String& rhs)" << endl;
    insert_count();
}
String::~String(){
    cout << "~String()" << endl;
    minus_count();
    if(is_zero_count()){
        cout << "释放" << endl;
        delete [] (_pstr - 4);
        _pstr = nullptr;
    }
}

String& String::operator=(const String& rhs){
    if(this != &rhs){
        minus_count();
        if (is_zero_count()){
            cout << "释放" << endl;
            delete[] (_pstr - 4);
            _pstr = nullptr;
        }
        _pstr = rhs._pstr;
        insert_count();
    }
    return *this;
}

void String::init_count(void){
    *((int*)(_pstr - _int_lenth)) = 1;
}
void String::insert_count(void){
    ++*((int*)(_pstr - _int_lenth));
}
void String::minus_count(void){
    --*((int*)(_pstr - _int_lenth));
}
bool String::is_zero_count(void) const{
    return *((int*)(_pstr - _int_lenth)) == 0;
}

void String::print(void) const{
    // cout << *((int *)(_pstr - _int_lenth)) << endl;
    cout << _pstr << endl;
}

size_t String::size() const{
    return strlen(_pstr);
}


const int& String::get_count(void) const{
    return *((int *)(_pstr - _int_lenth));
}

String::CharProxy String::operator[](int index){
    if(index >= size()){
        throw "访问越界";
    }
    return CharProxy(*this, index);
}
const char& String::operator[](int index) const{
    if(index >= size()){
        throw "访问越界";
    }
    return _pstr[index];
}


String::CharProxy::CharProxy(String& self, int index)
    : _self(self)
    , _index(index){
}



void String::CharProxy::operator=(const char& ch){
    if(_self.get_count() > 1){
        _self.minus_count();
        char* temp = new char[_int_lenth + _self.size() + 1] + _int_lenth;
        strcpy(temp, _self._pstr);
        _self._pstr = temp;
        _self.init_count();
    }
    _self._pstr[_index] = ch;
}



String::CharProxy::operator char(){
    return _self._pstr[_index];
}

int main(void)
{
    String S1("huzhu");
    String S2(S1);
    String S3("wode");
    S3.print();
    S3 = S2;
    S2.print();
    S1.print();

    S3[0] = 'H';
    cout << S3[0] << endl;
    S2.print();
    S3.print();
    S1.print();
    
    return 0;
}